/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
package fr.jade.fraclite.orb;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import fr.jade.fraclite.orb.api.Binder;
import fr.jade.fraclite.orb.io.RmiObjectInputStream;
import fr.jade.fraclite.orb.io.RmiObjectOutputStream;
import fr.jade.fraclite.orb.io.messages.AdminMessage;
import fr.jade.fraclite.orb.io.messages.RpcRequest;

public class SkeletonTask implements Runnable {

  protected Socket s;
  protected ObjectInputStream ois;
  protected ObjectOutputStream oos;
  protected ExecutorService es;
  protected Map<Long,Object> targets;
  boolean started = true;
  
  public SkeletonTask(Socket s, Map<Long,Object> targets, Binder binder)throws IOException{
    this.s = s;
    this.ois = new RmiObjectInputStream(s.getInputStream(), binder);
    this.oos = new RmiObjectOutputStream(s.getOutputStream(), binder);
    this.targets = targets;
    System.out.println("[skel] create connection on port "+s.getLocalPort());
  }
  
  @Override
  public void run (){
    try{
      while(started){
        Object req = ois.readObject();
        if(req instanceof AdminMessage){
          handleAdminMessage(req);
        }else{
          RpcRequest id = (RpcRequest)req;
          Object target = targets.get(id.getItfId());
          Object result = null;
          try{
            Method m = target.getClass().getMethod(id.getMethodName(), id.getArgTypes());
            System.out.println("[skel]"+id.getItfId()+" "+m.toGenericString());
            result = m.invoke(target, id.getArgs());
          }catch(InvocationTargetException e){
            result = e;
          }catch(Exception e){
            e.printStackTrace();
          }
          try {
            oos.writeObject(result);
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }catch(Exception e){
      e.printStackTrace();
    }
  }
  
  protected void handleAdminMessage(Object req) {
    switch ((AdminMessage)req){
    case SHUTDOWN:
      try{
      started = false;
      ois.close();
      oos.close();
      s.close();
      }catch(IOException ignored){}
      break;
    }
  }

}
